﻿
namespace GACore.Structures
{
	public class FitnessValue
	{
		private int points;
		public int Points
		{
			get { return points; }
			set { points = value; }
		}

		private int tokensWon;
		public int TokensWon
		{
			get { return tokensWon; }
			set { tokensWon = value; }
		}

		private int tokensLost;
		public int TokensLost
		{
			get { return tokensLost; }
			set { tokensLost = value; }
		}

		private int games;
		public int Games
		{
			get { return games; }
			set { games = value; }
		}

		private int ownCorners;
		public int OwnCorners
		{
			get { return ownCorners; }
			set { ownCorners = value; }
		}

		private int ownMobility;
		public int OwnMobility
		{
			get { return ownMobility; }
			set { ownMobility = value; }
		}

		private int opponentMobility;
		public int OpponentMobility
		{
			get { return opponentMobility; }
			set { opponentMobility = value; }
		}

		private double avg;
		public double Avg
		{
			get { return this.avg; }
			set { this.avg = value; }
		}

		private double value;
		public double Value
		{
			get { return this.value; }
			set { this.value = value; }
		}

		public static bool operator <(FitnessValue value1, FitnessValue value2)
		{
			return value1.avg < value2.avg;
		}

		public static bool operator >(FitnessValue value1, FitnessValue value2)
		{
			return value2 < value1;
		}

		internal void Reset()
		{
			points = 0;
			tokensWon = 0;
			tokensLost = 0;
			this.tokensWon = 0;
			this.tokensLost = 0;
			this.ownMobility = 0;
			this.opponentMobility = 0;
			this.ownCorners = 0;
			this.games = 0;
		}

		internal void ComputeAvg()
		{
			avg = (4 * avg + value) / 5;
		}

		public void AddResult(bool won, int ownTokens, int opponentTokens, int ownMobility, int opponentMobility, int ownCorners)
		{
			this.games++;
			if (won)
			{
				this.points++;
			}
			this.tokensWon += ownTokens;
			this.tokensLost += opponentTokens;
			this.ownMobility += ownMobility;
			this.opponentMobility += opponentMobility;
			this.ownCorners += ownCorners;

			double mobFactor = ((double)this.ownMobility) / (this.ownMobility + this.opponentMobility);
			this.value = (this.ownCorners / 4 * this.games) * (mobFactor + (this.ownCorners / 4 * this.games) + (this.points / this.games));
		}

		public override string ToString()
		{
			return "Gewinnrate: " + points + "/" + games + ", Ecken besetzt: " + ownCorners + "/" + (4 * games)
				+ ", Mobilitätsverhältnis: " + ownMobility + "/" + opponentMobility + ", Gesamtwert: " + avg;
		}
	}
}
